// 版权所有2016 Go作者。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 支持清洁剂。请参阅runtime/cgo/sigaction.go。

// go:build（linux&&amd64）| |（freebsd&&amd64）| |（linux&&arm64）| |（linux&&ppc64le）
// /+build linux，amd64 freebsd，amd64 linux，arm64 linux，ppc64le 

package runtime

import "unsafe"

// /|当它链接到
// /程序时，由运行时/cgo填写，因此只有在使用cgo时才是非零的。
// go:linkname\u cgo\u sigaction\u cgo\u sigaction 
var _cgo_sigaction unsafe.Pointer

// go:nosplit 
// go:nowritebarrierrec 
func sigaction(sig uint32, new, old *sigactiont) {
	// racewalk.go避免向包运行时添加消毒指令，
	// 但我们可能在这里调用指令化的C函数，
	// 所以我们需要正确标记指针参数。
	// 
	// 将输入标记为在调用
	// 之前写入，将输出标记为在调用后读取。
	if msanenabled && new != nil {
		msanwrite(unsafe.Pointer(new), unsafe.Sizeof(*new))
	}

	if _cgo_sigaction == nil || inForkedChild {
		sysSigaction(sig, new, old)
	} else {
		// 我们需要调用_cgo_sigaction，这意味着我们需要一个足够大的堆栈
		// 用于C。更复杂的是，我们可能在libpreinit（在
		// 运行时初始化之前）或异步信号处理程序中（使用
		// 当前线程在goroutines之间转换，或使用g0 
		// 系统堆栈已在使用）.

		var ret int32

		var g *g
		if mainStarted {
			g = getg()
		}
		sp := uintptr(unsafe.Pointer(&sig))
		switch {
		case g == nil:
			// 没有g:我们在C堆栈或信号堆栈上。
			ret = callCgoSigaction(uintptr(sig), new, old)
		case sp < g.stack.lo || sp >= g.stack.hi:
			// 我们不再在g堆栈上，所以我们必须处理信号。这是
			// 可能是我们在g 
			// 和g0之间的转换期间中断了线程，所以我们应该留在当前堆栈上以避免损坏g0。
			ret = callCgoSigaction(uintptr(sig), new, old)
		default:
			// 我们在g的堆栈上运行，因此不是在信号处理程序中就是在
			// 信号处理程序设置了正确的g。如果在gsignal或g0上，
			// systemstack将直接进行调用；否则，它将切换到
			// g0以确保我们有足够的空间调用libc函数。
			// 
			// 我们传递给systemstack的函数文本不是nosplit，而是
			// 没关系：我们将在一个新的、干净的系统堆栈上运行，因此堆栈
			// 检查无论如何都会成功。
			systemstack(func() {
				ret = callCgoSigaction(uintptr(sig), new, old)
			})
		}

		const EINVAL = 22
		if ret == EINVAL {
			// libc为pthreads保留某些信号（通常为32-33），而
			// 为这些信号上的sigaction调用返回EINVAL。如果我们得到EINVAL，
			// 返回直接进行系统调用。
			sysSigaction(sig, new, old)
		}
	}

	if msanenabled && old != nil {
		msanread(unsafe.Pointer(old), unsafe.Sizeof(*old))
	}
}

// callCgoSigaction使用GCC调用约定在运行时/cgo包
// 中调用sigaction函数。它在汇编中实现。
// go：noescape 
func callCgoSigaction(sig uintptr, new, old *sigactiont) int32
